package com.wisecoach.gatewayplus.transaction.tx;

import com.wisecoach.gatewayplus.bind.ContractArgs;
import com.wisecoach.gatewayplus.bind.ContractCommand;
import com.wisecoach.gatewayplus.transaction.ChaincodeException;
import com.wisecoach.gatewayplus.transaction.ContractExecutor;
import com.wisecoach.gatewayplus.transaction.SubmitTxContext;
import com.wisecoach.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.client.*;

/**
 * {@code @author:} wisecoach
 * {@code @date:} 2023/6/15 下午11:49
 * {@code @version:} 1.0.0
 */
@Slf4j
public class SubmitTxContractExecutor implements ContractExecutor {

    private final SubmitTxResource resource;

    public SubmitTxContractExecutor(SubmitTxResource resource) {
        this.resource = resource;
    }

    /**
     * evaluate只需要正常地调用evaluate即可
     * @param contract 要执行的链码对象
     * @param command 要执行的链码信息
     * @param args 链码交易参数
     */
    @Override
    public byte[] evaluate(Contract contract, ContractCommand command, ContractArgs args) {
        try {
            Proposal.Builder builder = contract.newProposal(command.getTransactionName());
            if (!CollectionUtils.isEmpty(args.getTransientMap())) {
                builder.putAllTransient(args.getTransientMap());
            }
            Proposal proposal = builder.addArguments(args.getArgs()).build();
            return proposal.evaluate();
        } catch (GatewayException e) {
            throw new ChaincodeException("链码执行失败", e);
        }
    }

    /**
     * 先进行背书，而不提交，将待提交的交易交给事务生成者来处理
     * @param contract 要执行的链码对象
     * @param command 要执行的链码信息
     * @param args 链码交易参数
     * @return 链码执行结果
     */
    @Override
    public byte[] submit(Contract contract, ContractCommand command, ContractArgs args) {
        try {
            Proposal.Builder builder = contract.newProposal(command.getTransactionName());
            if (!CollectionUtils.isEmpty(args.getTransientMap())) {
                builder.putAllTransient(args.getTransientMap());
            }
            Proposal proposal = builder.addArguments(args.getArgs()).build();
            Transaction transaction = proposal.endorse();
            log.debug(String.format("将交易%s放入待提交队列", transaction.getTransactionId()));
            resource.pushTx(new SubmitTxContext(transaction));
            return transaction.getResult();
        } catch (EndorseException e) {
            throw new ChaincodeException("链码执行失败", e);
        }
    }
}
